home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / util / libs / mufs_usergroup.lha / usergroup / getutent.c < prev    next >
C/C++ Source or Header  |  1992-09-02  |  12KB  |  529 lines

  1. RCS_ID_C="$Id: getutent.c,v 4.1 1994/05/16 14:09:07 ppessi Exp $";
  2. /*
  3.  * Login database functions
  4.  *
  5.  * Author: ppessi <Pekka.Pessi@hut.fi>
  6.  *
  7.  * This file is part of the AmiTCP/IP usergroup.library.
  8.  *
  9.  * Copyright ⌐ 1993 AmiTCP/IP Group, <AmiTCP-Group@hut.fi>
  10.  *                  Helsinki University of Technology, Finland.
  11.  *
  12.  * Created      : Sun Nov 28 17:45:55 1993 ppessi
  13.  * Last modified: Mon May 16 12:57:05 1994 ppessi
  14.  *
  15.  * $Log: getutent.c,v $
  16.  * Revision 4.1  1994/05/16  14:09:07  ppessi
  17.  * Fixed some outdated typecasts
  18.  *
  19.  * Revision 2.4  1994/02/27  19:15:26  ppessi
  20.  * Removed getutsid() as obsoilete
  21.  *
  22.  * Revision 2.3  1994/02/22  03:01:12  ppessi
  23.  * Removed tty from logging information
  24.  *
  25.  * Revision 2.2  1994/02/17  12:11:55  ppessi
  26.  * Release 2
  27.  *
  28.  * Revision 2.1  1994/02/17  02:21:06  ppessi
  29.  * Saving before downgrading library
  30.  *
  31.  */
  32.  
  33. /****** usergroup.library/getutent *******************************************
  34.  
  35.     NAME
  36.         getutsid, getutent, setutent, endutent - utmp database operations
  37.  
  38.     SYNOPSIS
  39.         #include <utmp.h>
  40.  
  41.         utmpent = getutsid(sid)
  42.            D0              D0
  43.         struct utmp *getutsid(long);
  44.  
  45.         utmpent = getutent()
  46.            D0
  47.         struct utmp *getutent(void);
  48.  
  49.         setutent()
  50.         void setutent(void);
  51.  
  52.         endutent()
  53.         void endutent(void);
  54.  
  55.     FUNCTION
  56.         These functions operate on the utmp database.  There is an utmp
  57.         entry for each active session.  A session is started with login
  58.         command and finished with logout command.
  59.  
  60.         The entry returned by each reading function is defined by the
  61.         structure utmp found in the include file <utmp.h>:
  62.  
  63.             struct utmp {
  64.               long    ut_time;              \* the login time *\
  65.               long    ut_sid;               \* session ID *\
  66.               char    ut_name[UT_NAMESIZE]; \* the login name *\
  67.               char    ut_line[UT_LINESIZE]; \* the name of login device *\
  68.               char    ut_host[UT_HOSTSIZE]; \* where the login originated *\
  69.             };
  70.  
  71.         The getutsid() function search the utmp database for the given
  72.         session id, returning the first one encountered.  The getutent()
  73.         function sequentially reads the utmp database.  Both functions also
  74.         open the utmp database, if necessary.
  75.  
  76.         The setutent() function opens the utmp database.  The
  77.         endutent() function closes the utmp database.  It is
  78.         recommended to call endutent() if the program won't access
  79.         utmp database any more.
  80.  
  81.     RESULTS
  82.         The functions getutsid() and getutent() return a pointer to the utmp
  83.         entry if successful; if the end of database is reached or an error
  84.         occurs a null pointer is returned.  The functions endutent() and
  85.         setutent() have no return value.
  86.  
  87.     ERRORS
  88.         [ENOENT] -- no utmp entries were available.
  89.  
  90.     SEE ALSO
  91.  
  92.     BUGS
  93.         The getutent() and getutsid() function leave their result in an
  94.         internal static object and return a pointer to that object.
  95.         Subsequent calls to the same function will modify the same object.
  96.  
  97.         Current implementation allows only one user to be logged in
  98.         concurrently.
  99.  
  100. *****************************************************************************
  101. *
  102. */
  103.  
  104. #include "base.h"
  105. #include "libfunc.h"
  106. #include "credential.h"
  107.  
  108. #include <utmp.h>
  109. #include <string.h>
  110. #include <exec/memory.h>
  111. #include <dos/dos.h>
  112.  
  113. #include <sys/time.h>
  114.  
  115. #define SINGLE_USER
  116.  
  117. ASM int R_gettimeofday(REG(a0) struct timeval *tvp, 
  118.                REG(a1) struct timezone *tzp);
  119.  
  120. #ifdef SINGLE_USER
  121. /*      
  122.  * These are simple routines for single-user environment
  123.  */
  124. void CleanupUTMP(void)
  125. {
  126. }
  127.  
  128. static short already_read = 0;
  129.  
  130. SAVEDS ASM void R_endutent(void)
  131. {
  132.   already_read = 0;
  133. }
  134. SAVEDS ASM void R_setutent(void)
  135. {
  136.   already_read = 0;
  137. }
  138.  
  139. SAVEDS ASM struct utmp *R_getutent(void)
  140. {
  141.   if (!already_read) {
  142.     static struct utmp utentbuf[1];
  143.  
  144.     already_read = 1;
  145.     *utentbuf = *CredentialBase->r_utmp;
  146.     return utentbuf;
  147.   }
  148.  
  149.   SetErrno(ENOENT);
  150.   return NULL;
  151. }
  152. #else
  153. static void lock_for_writing(void)
  154. {
  155. }
  156.  
  157. static void unlock_for_writing(void)
  158. {
  159. }
  160.  
  161. #define UTENTS 2
  162. static short utent_left;
  163. static struct utmp *utentbuf = NULL, *utent = NULL;
  164. static BPTR utfile = NULL;
  165. static LONG uttell;
  166.  
  167. void CleanupUTMP(void)
  168. {
  169.   R_endutent();
  170.  
  171.   if (utentbuf != NULL) {
  172.     FreeVec(utentbuf), utentbuf = NULL;
  173.   }
  174. }
  175.  
  176. SAVEDS ASM void R_endutent(void)
  177. {
  178.   if (utfile != NULL) {
  179.     Close(utfile), utfile = NULL;
  180.   }
  181. }
  182.  
  183. SAVEDS ASM void R_setutent(void)
  184. {
  185.   if (utentbuf == NULL)
  186.     utentbuf = AllocVec(sizeof(*utent) * UTENTS, MEMF_CLEAR | MEMF_PUBLIC);
  187.   if (utentbuf != NULL) {
  188.     utent_left = 0;
  189.     if (utfile == NULL) {
  190.       utfile = Open(_PATH_UTMP, MODE_READWRITE);
  191.     } else {
  192.       Seek(utfile, 0, OFFSET_BEGINNING);
  193.     }
  194.   }
  195. }
  196.  
  197. SAVEDS ASM struct utmp *R_getutent(void)
  198. {
  199.   if (utentbuf == NULL) {
  200.     R_setutent();
  201.   }
  202.  
  203.   if (utfile) {
  204.     for (;;) {
  205.       if (utent_left == 0) {
  206.     LONG read;
  207.     
  208.     uttell = Seek(utfile, 0, OFFSET_CURRENT);
  209.     read = Read(utfile, utentbuf, sizeof(*utent) * UTENTS);
  210.  
  211.     utent = utentbuf;
  212.     if (read >= sizeof(*utent)) {
  213.       utent_left = read / sizeof(*utent);
  214.     } else {
  215.       break;
  216.     }
  217.       } else {
  218.     uttell += sizeof(*utent);
  219.       }
  220.  
  221.       utent_left--;
  222.       if (utent->ut_time != 0)
  223.     return utent++;
  224.       utent++;
  225.     }
  226.  
  227.     SetErrno(ENOENT);
  228.   } else {
  229.     if (utentbuf)
  230.       SetErrno(ENOENT);
  231.     else
  232.       SetErrno(ENOMEM);
  233.   }
  234.  
  235.   return NULL;
  236. }
  237.  
  238. SAVEDS ASM struct utmp *R_getutsid(REG(d0) pid_t sid)
  239. {
  240.   struct utmp *ut;
  241.  
  242.   for (R_setutent(); ut = R_getutent();) {
  243.     if (ut->ut_sid == sid)
  244.       return ut;
  245.   }
  246.  
  247.   return NULL;
  248. }
  249. #endif
  250.  
  251. /****** usergroup.library/getlastlog *******************************************
  252.  
  253.     NAME
  254.         getlastlog - get lastlog database entry
  255.  
  256.     SYNOPSIS
  257.         #include <utmp.h>
  258.  
  259.         lastlog = getlastlog(uid)
  260.            D0                D0
  261.         struct lastlog *getlastlog(uid_t);
  262.  
  263.     FUNCTION
  264.  
  265.         The getlastlog() function search the lastlog database for the given
  266.         user id. There should be an lastlog entry for each user.  A lastlog
  267.         entry with ll_time being zero means that user has never logged in
  268.         this system.
  269.  
  270.         The entry returned by getlastlog is defined by the structure lastlog
  271.         found in the include file <utmp.h>:
  272.  
  273.           struct lastlog {                                              
  274.             long  ll_time;              \* the login time *\            
  275.             uid_t ll_uid;               \* user ID *\                   
  276.             char  ll_name[UT_NAMESIZE]; \* the login name *\            
  277.             char  ll_line[UT_LINESIZE]; \* the name of login device *\  
  278.             char  ll_host[UT_HOSTSIZE]; \* where the login originated *\
  279.               };
  280.  
  281.     RESULTS
  282.         The function getlastlog() returns a pointer to the lastlog entry if
  283.         successful; if an error occurs a null pointer is returned.
  284.  
  285.     ERRORS
  286.         [ENOENT] -- no lastlog entry was found
  287.         [EINVAL] -- the user ID was illegal
  288.  
  289.     SEE ALSO
  290.         setlastlog()
  291.  
  292.     BUGS
  293.         The getlastlog() function leaves its result in an internal static
  294.         object and return a pointer to that object.  Subsequent calls to the
  295.         same function will modify the same object.
  296.  
  297.         Current implementation stores only the lastlog data of the latest
  298.         user logged in.
  299.  
  300. *****************************************************************************
  301. *
  302. */
  303.  
  304. #ifdef SINGLE_USER
  305.  
  306. SAVEDS ASM struct lastlog *R_getlastlog(REG(d0) uid_t uid)
  307. {
  308.   static struct lastlog ll[1];
  309.  
  310.   if (uid == CredentialBase->r_lastlog->ll_uid) {
  311.     *ll = *CredentialBase->r_lastlog;
  312.   } else {
  313.     bzero(ll, sizeof(*ll));
  314.     ll->ll_uid = uid;
  315.   }
  316.  
  317.   return ll;
  318. }
  319. #else
  320. static LONG lltell = 0; 
  321.  
  322. SAVEDS ASM struct lastlog *R_getlastlog(REG(d0) uid_t uid)
  323. {
  324.   static struct lastlog ll[1];
  325.   BPTR llfile = Open(_PATH_LASTLOG, MODE_OLDFILE);
  326.   int never = 1;
  327.  
  328.   lltell = 0;
  329.   
  330.   if (llfile) {
  331.     while (Read(llfile, ll, sizeof(*ll)) == sizeof(*ll)) {
  332.       lltell += sizeof(*ll);
  333.       if (ll->ll_uid == uid) {
  334.     never = 0;
  335.     break;
  336.       }
  337.     }
  338.     Close(llfile);
  339.   }
  340.  
  341.   if (never) {
  342.     ll->ll_time = 0;
  343.     ll->ll_uid = uid;
  344.     ll->ll_name[0] = '\0';
  345.     ll->ll_line[0] = '\0';
  346.     ll->ll_host[0] = '\0';
  347.     lltell = -1;
  348.   }
  349.  
  350.   return ll;
  351. }
  352. #endif
  353.  
  354. /****** usergroup.library/setlastlog ***************************************
  355.  
  356.     NAME
  357.         setlastlog - login an user
  358.  
  359.     SYNOPSIS
  360.         #include <utmp.h>
  361.  
  362.         lastlogin = setlastlog(uid, name, console, host)
  363.  
  364.         struct lastlog setlastlog(uid_t, char *, char *, char *);
  365.  
  366.     FUNCTION
  367.         The setlastlog function is used to register user logging in.  Each
  368.         time a user is logging in, the function setlastlog() should be
  369.         called to register that event.
  370.  
  371.     INPUTS
  372.         uid     -- the uid of user logging in
  373.     name    -- the user login name
  374.     console -- the console handler name (from ug_GetConsole())
  375.     host    -- the host which the user is logging in from
  376.  
  377.     RESULTS
  378.         The setlastlog() function returns an success indicator, 0 if the
  379.         call was successful, -1 otherwise.  The error code is set if an
  380.         error occurs.
  381.  
  382.     ERRORS
  383.         The setlastlog() can have following error codes:
  384.     [EFAULT] -- the utmp entry cannot be accessed
  385.     [ENOMEM] -- the memory has been exhausted
  386.     [ENOENT] -- cannot access utmp database
  387.  
  388.     BUGS
  389.         Current implementation stores only the lastlog data of the latest
  390.         user logged in.
  391.  
  392.     FILES
  393.  
  394.     SEE ALSO
  395.         getutent(), getlastlog()
  396.  
  397. *****************************************************************************
  398. */
  399.  
  400. #ifdef SINGLE_USER
  401. /*
  402.  * This is somewhat simplified version
  403.  */
  404. SAVEDS ASM int
  405. R_setlastlog(REG(d0) uid_t uid, 
  406.          REG(a0) char *name, REG(a1) char *host)
  407. {
  408.   short error = 0;
  409.   struct proc *p = procfind(NULL);
  410.   pid_t sid = p->p_session->s_leader;
  411.  
  412.   if (name == NULL) {
  413.     error = EFAULT;
  414.   } else {
  415.     struct utmp utmp[1];
  416.     struct timeval now[1]; 
  417.  
  418.     bzero((void *)utmp, sizeof(*utmp));
  419.  
  420.     R_gettimeofday(now, NULL);
  421.     utmp->ut_time = now->tv_sec;
  422.     utmp->ut_sid = (long)sid;
  423.  
  424.     strncpy(utmp->ut_name, name, sizeof(utmp->ut_name));
  425.     if (host)
  426.       strncpy(utmp->ut_host, host, sizeof(utmp->ut_host));
  427.       
  428.     *CredentialBase->r_utmp = *utmp;
  429.     
  430.     /*
  431.      * This trick requires that 
  432.      * lastlog and utmp are essentially identical..
  433.      */
  434.     utmp->ut_sid = (long) uid;
  435.     *CredentialBase->r_lastlog = *(struct lastlog *)utmp;
  436.     return 0;
  437.   }
  438.  
  439.   SetErrno(error);
  440.   return -1;
  441. }
  442. #else /* SINGLE_USER */
  443. SAVEDS ASM int
  444. R_setlastlog(REG(d0) uid_t uid, 
  445.          REG(a0) char *name, REG(a1) char *host)
  446. {
  447.   short error = 0;
  448.   struct proc *p = procfind(NULL);
  449.   pid_t sid = p->p_session->s_leader;
  450.  
  451.   if (name == NULL || con == NULL) {
  452.     error = EFAULT;
  453.   } else {
  454.     struct utmp *oldut, utmp[1];
  455.     struct timeval now[1]; 
  456.  
  457.     bzero((void *)utmp, sizeof(*utmp));
  458.     R_gettimeofday(now, NULL);
  459.     utmp->ut_time = now->tv_sec;
  460.     utmp->ut_sid = sid;
  461.     strncpy(utmp->ut_name, name, sizeof(utmp->ut_name));
  462.     if (sid != 0) 
  463.       strncpy(utmp->ut_line, con, sizeof(utmp->ut_line));
  464.     else
  465.       strcpy(utmp->ut_line, "ALL");
  466.     if (host)
  467.       strncpy(utmp->ut_host, host, sizeof(utmp->ut_host));
  468.  
  469.     R_setutent();
  470.  
  471.     /* Writing lock */
  472.     lock_for_writing();
  473.  
  474.     if (utentbuf == NULL) {
  475.       error = ENOMEM;
  476.     } else if (utfile == NULL) {
  477.       error = ENOENT;
  478.     } else {
  479.       LONG utslot = -1;
  480.  
  481.       while (oldut = R_getutent()) {
  482.     if (oldut->ut_sid == sid) {
  483.       utslot = uttell;
  484.       break;
  485.     }
  486.     if (oldut->ut_time == 0 && utslot == -1) {
  487.       utslot = uttell;
  488.     }
  489.       }
  490.       if (oldut == NULL)
  491.     utslot = uttell;
  492.  
  493.       Seek(utfile, uttell, OFFSET_BEGINNING);
  494.       Write(utfile, utmp, sizeof(*utmp));
  495.     }
  496.  
  497.     R_endutent();
  498.  
  499.     {
  500.       BPTR llfile = Open(_PATH_LASTLOG, MODE_READWRITE);
  501.       
  502.       utmp->ut_sid = (long)uid;
  503.  
  504.       if (llfile) {
  505.     if (lltell > 0) {
  506.       Seek(llfile, lltell, OFFSET_BEGINNING);
  507.     } else {
  508.       LONG tell;
  509.       Seek(llfile, 0, OFFSET_END);
  510.       tell = Seek(llfile, 0, OFFSET_CURRENT);
  511.       tell = (tell / sizeof(*utmp)) * sizeof(*utmp);
  512.       Seek(llfile, tell, OFFSET_BEGINNING);
  513.     }
  514.     Write(llfile, utmp, sizeof(*utmp));
  515.     Close(llfile);
  516.       }
  517.     }
  518.     unlock_for_writing();
  519.   }
  520.  
  521.   if (error != 0) {
  522.     SetErrno(error);
  523.     return NULL;
  524.   } else {
  525.     return ll;
  526.   }
  527. }
  528. #endif
  529.